using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Xml;

namespace miciv
{
    public class ComponentManager<T, C, M> : IComponentManager
        where M : class, IComponentManager
        where T : ComponentPrototypeBase<M>, new()
        where C : ComponentInstanceBase<T>, new()
    {
        protected Hashtable m_htblPrototypes;
        protected List<IComponentInstance> m_lstInstances;
        protected List<string> m_vstrAvailableComponentNames;
        protected CoreContext m_coreContext;
        protected CoreManager m_coreManager;

        public ComponentManager(CoreContext _coreContext)
        {
            this.m_coreContext = _coreContext;
            this.m_coreManager = this.m_coreContext.CoreManager;
            this.m_vstrAvailableComponentNames = new List<string>();
            this.m_htblPrototypes = new Hashtable();
            this.m_lstInstances = new List<IComponentInstance>();
        }

        #region IComponentPrototypeManager Membres

        virtual public List<string> AvailableComponentNames
        {
            get
            {
                return this.m_vstrAvailableComponentNames;
            }
        }

        virtual public CoreContext CoreContext
        {
            get
            {
                return this.m_coreContext;
            }
        }

        virtual public CoreManager CoreManager
        {
            get
            {
                return this.m_coreManager;
            }
        }

        virtual public IComponentPrototype CreatePrototype(EntityPrototype _enProto, XmlElement _xmlConfig)
        {
            T coProto = new T();
            if ((false != coProto.Initialize(_enProto, _xmlConfig, this)) && (false == this.m_htblPrototypes.ContainsKey(coProto.ID)))
            {
                this.m_htblPrototypes.Add(coProto.ID, coProto);
                return coProto;
            }
            return null;
        }

        virtual public void ReleasePrototype(IComponentPrototype _Proto)
        {
            T coProto = _Proto as T;
            if ((null != coProto) && (false != this.m_htblPrototypes.ContainsKey(coProto.ID)))
            {
                this.m_htblPrototypes.Remove(coProto.ID);
            }
        }

        virtual public void Release()
        {
            foreach (IComponentInstance coInstance in this.m_lstInstances)
            {
                coInstance.Release();
            }
            foreach (DictionaryEntry de in this.m_htblPrototypes)
            {
                (de.Value as IComponentPrototype).Release();
            }
            this.m_htblPrototypes.Clear();
            this.m_lstInstances.Clear();
            this.m_vstrAvailableComponentNames.Clear();
        }

        virtual public IComponentInstance CreateInstance(Entity _entity, IComponentPrototype _coProto)
        {
            C coInstance = new C();
            if (false != coInstance.Initialize(_entity, _coProto))
            {
                this.m_lstInstances.Add(coInstance);
                return coInstance;
            }
            return null;
        }

        virtual public void ReleaseInstance(IComponentInstance _coInstance)
        {
            if (this.m_lstInstances.Contains(_coInstance))
            {
                _coInstance.Release();
                this.m_lstInstances.Remove(_coInstance);
            }
        }

        #endregion
    }
}
